/*
    文件内容: 封装ThreadPool相关操作,线程池
    文件名: ThreadPool.cpp
    作者: 中国好青年(码农论坛)
    时间: 2024/9/21
*/

#include "ThreadPool.h"

/* 
    函数名: ThreadPool()
    返回值: 无
    参  数: size_t threadnum, 线程池线程个数
    函数作用: 构造函数,创建线程池对象,等待唤醒
*/
ThreadPool::ThreadPool(size_t threadnum, const std::string& threadtype):stop_(false), threadtype_(threadtype)
{
    // 启动threadnum个线程，每个线程将阻塞在条件变量上。
    for (size_t ii = 0; ii < threadnum; ii++)
    {   
        // 用lambda函创建线程。
        threads_.emplace_back([this,ii]
        {   
            debug("index %d create %s thread(%d)\n", ii, threadtype_.c_str(), syscall(SYS_gettid));
            while (stop_ == false)
            {
                std::function<void()> task;       // 用于存放出队的元素。
                {   
                    // 锁作用域的开始。 ///////////////////////////////////
                    std::unique_lock<std::mutex> lock(this->mutex_);
                    // 等待生产者的条件变量。
                    while(this->taskqueue_.empty() && (this -> stop_ == false))
                        this->condition_.wait(lock);
                    /* 第二种写法
                    this->condition_.wait(lock, [this]
                    {
                        return ((this->stop_==true) || (this->taskqueue_.empty()==false));
                    });
                    */
                    // 在线程池停止之前，如果队列中还有任务，执行完再退出。
                    if ((this->stop_==true)&&(this->taskqueue_.empty()==true)) return;

                    // 出队一个任务。
                    task = std::move(this->taskqueue_.front());
                    this->taskqueue_.pop();
                }// 锁作用域的结束。 ///////////////////////////////////
                task();  // 执行任务。
                debug("%s thread(%d) exec task end\n", threadtype_.c_str(), syscall(SYS_gettid));
            }
        });
    }
}

/* 
    函数名: addtask()
    返回值: 无
    参  数: std::function<void()> task,函数对象
    函数作用: 向任务队列添加队列
*/
void ThreadPool::addtask(std::function<void()> task)
{   

    {   // 锁作用域的开始。 /////////////////////////////////// 
        std::lock_guard<std::mutex> lock(mutex_);
        taskqueue_.push(task);
    }   // 锁作用域的结束。 ///////////////////////////////////

    condition_.notify_one();   // 唤醒一个线程。
}

/* 
    函数名: ~ThreadPool()
    返回值: 无
    参  数: std::function<void()> task,函数对象
    函数作用: 析构函数, 唤醒线程处理剩余事务, 等待线程退出
*/
ThreadPool::~ThreadPool()
{   
   stop();
}

/* 
    函数名: size()
    返回值: 无
    参  数: 无
    函数作用: 返回线程池个数
*/
size_t ThreadPool::size()
{
    return threads_.size();
}

/* 
    函数名: void stop()
    返回值: 无
    参  数: 无
    函数作用: 处理线程终止后事务，join线程
*/
void ThreadPool::stop()
{
    if(stop_)
    {
        return;
    }
    stop_ = true;
    // 唤醒全部的线程。
    condition_.notify_all(); 
    // 等待全部线程执行完任务后退出。
    for (std::thread &th : threads_) 
        th.join();

    debug("%s 线程停止\n", threadtype_.c_str());
}